<?php

namespace Biz\service\bizAd;

use Biz\model\bizAd\AdPlan as mAdPlan;
use Biz\model\bizAd\AdRechargeOrder as mAdRechargeOrder;
use Biz\model\bizAd\AdWalletLog as mAdWalletLog;
use Biz\model\bizAd\AdWalletMonthSettle as mAdWalletMonthSettle;
use Biz\pockets\constInterface\BizAd as iBizAd;
use Biz\pockets\excel\DownExcel;
use Medoo\Medoo;

class AdBizExport
{
    const EXPORT_TYPE_RECHARGE = 1; //导出充值记录
    const EXPORT_TYPE_CONSUME_PLAN_END = 2;  //导出消耗记录结束的
    const EXPORT_TYPE_CONSUME_PLAN_GOING = 3;  //导出消耗记录进行中
    const EXPORT_TYPE_BALANCE = 4;  //导出余额

    const ERROR_CODE_EMPTY = 5000; //数据为空
    const ERROR_CODE_UNSUPPORT_TYPE = 5001; //不支持的导出类型
    const ERROR_CODE_CONDITION = 5002; //查询条件错误

    const ERROR_CODE = [
        self::ERROR_CODE_EMPTY,
        self::ERROR_CODE_UNSUPPORT_TYPE,
        self::ERROR_CODE_CONDITION,
    ];

    /**
     * 导出账单
     * @param $type
     * @param $startDate
     * @param $endDate
     * @return void
     * @throws \Exception
     */
    public static function exportData($type, $startDate, $endDate)
    {
        switch ($type) {
            case self::EXPORT_TYPE_RECHARGE:
                self::exportRecharge($startDate, $endDate);
                break;
            case self::EXPORT_TYPE_CONSUME_PLAN_END:
                self::exportPlanEnd($startDate, $endDate);
                break;
            case self::EXPORT_TYPE_CONSUME_PLAN_GOING:
                self::exportPlanGoing($startDate, $endDate);
                break;
            case self::EXPORT_TYPE_BALANCE:
                self::exportBalance($startDate, $endDate);
                break;
            default:
                throw new \Exception('不支持的导出类型', self::ERROR_CODE_UNSUPPORT_TYPE);
        }
    }

    /**
     * 导出充值订单
     * @param $startDate
     * @param $endDate
     * @return void
     */
    public static function exportRecharge($startDate, $endDate)
    {
        $exportData = [];

        $where = [
            'op_type' => [mAdWalletLog::OP_TYPE_RECHARGE, mAdWalletLog::OP_TYPE_CASHOUT],
            'create_time[>=]' => date('Y-m-d 00:00:00', strtotime($startDate)),
            'create_time[<=]' => date('Y-m-d 23:59:59', strtotime($endDate)),
        ];

        mAdWalletLog::dataChunk($where, 1000, function ($data) use (&$exportData) {

            if (empty($data)) {
                return false;
            }

            $uids = array_column($data, 'uid');

            $users = AdUser::formatUserInfo($uids);

            $dsns = array_column($data, 'op_rel_id');

            $orders = mAdRechargeOrder::dataSelect(['dsn' => $dsns]);

            $orderMap = $orders ? array_column($orders, null, 'dsn') : [];

            foreach ($data as $row) {
                $user = $users[$row['uid']];
                if (mAdWalletLog::OP_TYPE_RECHARGE == $row['op_type']) {
                    $order = $orderMap[$row['op_rel_id']];
                    $exportData[] = [
                        'month' => date('Ym', strtotime($row['create_time'])),
                        'dsn' => $order['dsn'] ?? '',
                        'bname' => $user['bname'] ?? '',
                        'bid' => $user['bid'] ?? '',
                        'uid' => $row['uid'],
                        'utype' => iBizAd::AD_UTYPES[$row['utype']],
                        'biz_name' => '效果广告充值',
                        'pay_date' => date('Ymd', $order['pay_time']),
                        'pay_platform' => mAdRechargeOrder::PAY_PLATFORM[$order['pay_platform']],
                        'trans_no' => $order['other_sn'],
                        'amount' => $row['amount'],
                        'give_amount' => 0.00,
                    ];
                } elseif (mAdWalletLog::OP_TYPE_CASHOUT == $row['op_type']) {
                    $exportData[] = [
                        'month' => date('Ym', strtotime($row['create_time'])),
                        'dsn' => '',
                        'bname' => $user['bname'] ?? '',
                        'bid' => $user['bid'] ?? '',
                        'uid' => $row['uid'],
                        'utype' => iBizAd::AD_UTYPES[$row['utype']],
                        'biz_name' => '效果广告退费',
                        'pay_date' => date('Ymd', strtotime($row['create_time'])),
                        'pay_platform' => '银行转账',
                        'trans_no' => $row['op_rel_id'],
                        'amount' => '-' . $row['amount'],
                        'give_amount' => 0.00,
                    ];
                }

            }

            return true;

        });

        if (empty($exportData)) {
            throw new \Exception('暂无导出数据', self::ERROR_CODE_EMPTY);
        }

        $header = [
            'month' => '月份',
            'dsn' => '充值订单号',
            'bname' => '商家名称',
            'bid' => '商家ID',
            'uid' => 'UID',
            'utype' => '商家身份',
            'biz_name' => '业务名称',
            'pay_date' => '支付时间（年月日)',
            'pay_platform' => '支付渠道（银行转账、微信、支付宝）',
            'trans_no' => '第三方交易流水号',
            'amount' => '充值金额',
            'give_amount' => '赠送金额'
        ];

        $downExcel = new DownExcel();

        $fileName = sprintf("%s%s", '充值表', date('Ymd'));

        $downExcel->setFileName($fileName);

        $downExcel->setSheetTitle(date('Ymd'));

        $downExcel->setTextFormat('J');

        $widths = [
            'A' => 15,
            'B' => 30,
            'C' => 30,
            'D' => 20,
            'E' => 20,
            'F' => 15,
            'G' => 20,
            'H' => 30,
            'I' => 40,
            'J' => 30,
            'K' => 15,
            'L' => 15,
        ];

        $downExcel->setWidth($widths);

        $downExcel->setDefaultStyleAlignment();

        $downExcel->create($exportData, $header);

    }

    /**
     * 导出账户余额
     * @param $startDate
     * @param $endDate
     * @return bool | void
     */
    public static function exportBalance($startDate, $endDate)
    {
        $exportData = [];

        if (date('Ym', strtotime($startDate)) != date('Ym', strtotime($endDate))) {
            throw new \Exception('开始和结束日期不是同一个月', self::ERROR_CODE_CONDITION);
        }

        $month = date('Ym', strtotime($startDate));

        if (date('Ym', time()) == $month) {
            throw new \Exception('当前月份数据尚未结算', self::ERROR_CODE_CONDITION);
        }

        $lastMonth = date('Ym', strtotime('-1 month', strtotime($startDate)));

        $where = [
            'month' => $month,
            'ORDER' => ['id' => 'ASC']
        ];

        mAdWalletMonthSettle::dataChunk($where, 1000, function ($data) use (&$exportData, $lastMonth) {

            if (empty($data)) {
                return false;
            }

            $uids = array_column($data, 'uid');

            $users = AdUser::formatUserInfo($uids);

            $lastMonthBalances = mAdWalletMonthSettle::dataSelect(['month' => $lastMonth, 'uid' => $uids]);

            $lastMonthBalanceMap = empty($lastMonthBalances) ? [] : array_column($lastMonthBalances, 'balance', 'uid');

            foreach ($data as $row) {

                $user = $users[$row['uid']];

                $lastMonthBalance = isset($lastMonthBalanceMap[$row['uid']]) ? $lastMonthBalanceMap[$row['uid']] : 0.00;

                $exportData[] = [
                    'month' => $row['month'],
                    'bname' => $user['bname'] ?? '',
                    'bid' => $user['bid'] ?? '',
                    'uid' => $row['uid'],
                    'utype' => iBizAd::AD_UTYPES[$row['utype']],
                    'biz_name' => '效果广告余额',
                    'balance_month_start' => $lastMonthBalance,
                    'balance_month_end' => $row['balance'],
                ];
            }

            return true;

        });

        if (empty($exportData)) {
            throw new \Exception('暂无导出数据', self::ERROR_CODE_EMPTY);
        }

        $header = [
            'month' => '月份',
            'bname' => '商家名称',
            'bid' => '商家ID',
            'uid' => 'UID',
            'utype' => '商家身份',
            'biz_name' => '业务名称',
            'balance_month_start' => '月初余额',
            'balance_month_end' => '月末余额'
        ];

        $downExcel = new DownExcel();

        $fileName = sprintf("%s%s", '广告账户余额', date('Ymd'));

        $downExcel->setFileName($fileName);

        $downExcel->setSheetTitle(date('Ymd'));

        $width = [
            'A' => 15,
            'B' => 20,
            'C' => 15,
            'D' => 20,
            'E' => 20,
            'F' => 30,
            'G' => 20,
            'H' => 20,
        ];

        $downExcel->setWidth($width);

        $downExcel->setDefaultStyleAlignment();

        $downExcel->create($exportData, $header);
    }

    /**
     * 导出消耗表-计划结束
     * @param $startDate
     * @param $endDate
     * @return false|void
     */
    public static function exportPlanEnd($startDate, $endDate)
    {
        $exportData = [];

        $currentTime = time();

        $where = [
            'AND' => [
                'OR' => [
                    'end_time[<]' => $currentTime,
                    'expose_count[>=]' => Medoo::raw("target_count"),
                ],
                'plan_status' => mAdPlan::PLAN_STATUS_OPEN,
                'create_time[>=]' => date('Y-m-d 00:00:00', strtotime($startDate)),
                'create_time[<=]' => date('Y-m-d 23:59:59', strtotime($endDate)),
            ],
            'ORDER' => ['id' => 'ASC']
        ];

        mAdPlan::dataChunk($where, 1000, function ($data) use (&$exportData) {

            if (empty($data)) {
                return false;
            }

            $uids = array_column($data, 'uid');

            $users = AdUser::formatUserInfo($uids);

            foreach ($data as $row) {

                $user = $users[$row['uid']] ?? [];

                $planState = mAdPlan::getPlanState($row);

                $exportData[] = [
                    'month' => date('Ym', strtotime($row['create_time'])),
                    'bname' => $user['bname'] ?? '',
                    'bid' => $user['bid'] ?? '',
                    'uid' => $row['uid'],
                    'utype' => iBizAd::AD_UTYPES[$row['utype']],
                    'biz_name' => '效果广告-CPM',
                    'plan_id' => $row['id'],
                    'ad_type' => mAdPlan::AD_TYPE[$row['ad_type']],
                    'plan_count' => $row['plan_count'],
                    'price' => $row['price'],
                    'buy_amount' => $row['buy_amount'],
                    'amount' => $row['amount'],
                    'refund_amount' => $row['refund_amount'],
                    'plan_status' => mAdPlan::PLAN_STATE[$planState],
                    'settle_status' => mAdPlan::SETTLE_STATUS_MAP[$row['settle_status']],
                    'start_time' => date('Ymd', $row['start_time']),
                    'end_time' => date('Ymd', $row['end_time']),
                ];

            }

            return true;

        });

        if (empty($exportData)) {
            throw new \Exception('暂无导出数据', self::ERROR_CODE_EMPTY);
        }

        $header = [
            'month' => '月份',
            'bname' => '商家名称',
            'bid' => '商家ID',
            'uid' => 'UID',
            'utype' => '商家身份',
            'biz_name' => '业务名称',
            'plan_id' => '计划id',
            'ad_type' => '投放形式',
            'plan_count' => '投放次数',
            'price' => '投放单价',
            'buy_amount' => '计划金额',
            'amount' => '实际金额',
            'refund_amount' => '返还金额',
            'plan_status' => '计划状态',
            'settle_status' => '结算状态',
            'start_time' => '计划开始时间',
            'end_time' => '计划结束时间',
        ];

        $downExcel = new DownExcel();

        $fileName = sprintf("%s%s", '消耗表-已结束计划', date('Ymd'));

        $downExcel->setFileName($fileName);

        $downExcel->setSheetTitle(date('Ymd'));

        $width = [
            'A' => 15,
            'B' => 20,
            'C' => 15,
            'D' => 20,
            'E' => 20,
            'F' => 20,
            'G' => 20,
            'H' => 20,
            'I' => 20,
            'J' => 20,
            'K' => 20,
            'L' => 20,
            'M' => 20,
            'N' => 20,
            'O' => 20,
            'P' => 20,
            'Q' => 20,
        ];

        $downExcel->setWidth($width);

        $downExcel->setDefaultStyleAlignment();

        $downExcel->create($exportData, $header);
    }

    /**
     * 导出消耗表-在途计划
     * @param $startDate
     * @param $endDate
     * @return false|void
     */
    public static function exportPlanGoing($startDate, $endDate)
    {
        $exportData = [];

        $currentTime = time();

        $where = [
            'start_time[<=]' => $currentTime,
            'end_time[>=]' => $currentTime,
            'expose_count[<]' => Medoo::raw("target_count"),
            'plan_status' => mAdPlan::PLAN_STATUS_OPEN,
            'create_time[>=]' => date('Y-m-d 00:00:00', strtotime($startDate)),
            'create_time[<=]' => date('Y-m-d 23:59:59', strtotime($endDate)),
            'ORDER' => ['id' => 'ASC']
        ];

        mAdPlan::dataChunk($where, 1000, function ($data) use (&$exportData) {

            if (empty($data)) {
                return false;
            }

            $uids = array_column($data, 'uid');

            $users = AdUser::formatUserInfo($uids);

            foreach ($data as $row) {

                $user = $users[$row['uid']] ?? [];

                $planState = mAdPlan::getPlanState($row);

                $exportData[] = [
                    'month' => date('Ym', strtotime($row['create_time'])),
                    'bname' => $user['bname'] ?? '',
                    'bid' => $user['bid'] ?? '',
                    'uid' => $row['uid'],
                    'utype' => iBizAd::AD_UTYPES[$row['utype']],
                    'biz_name' => '效果广告-CPM',
                    'plan_id' => $row['id'],
                    'ad_type' => mAdPlan::AD_TYPE[$row['ad_type']],
                    'plan_count' => $row['plan_count'],
                    'price' => $row['price'],
                    'buy_amount' => $row['buy_amount'],
                    'plan_status' => mAdPlan::PLAN_STATE[$planState],
                    'start_time' => date('Ymd', $row['start_time']),
                    'end_time' => date('Ymd', $row['end_time']),
                ];

            }

            return true;

        });

        if (empty($exportData)) {
            throw new \Exception('暂无导出数据', self::ERROR_CODE_EMPTY);
        }

        $header = [
            'month' => '月份',
            'bname' => '商家名称',
            'bid' => '商家ID',
            'uid' => 'UID',
            'utype' => '商家身份',
            'biz_name' => '业务名称',
            'plan_id' => '计划id',
            'ad_type' => '投放形式',
            'plan_count' => '投放次数',
            'price' => '投放单价',
            'buy_amount' => '计划金额',
            'plan_status' => '计划状态',
            'start_time' => '计划开始时间',
            'end_time' => '计划结束时间',
        ];

        $downExcel = new DownExcel();

        $fileName = sprintf("%s%s", '消耗表-在途中计划', date('Ymd'));

        $downExcel->setFileName($fileName);

        $downExcel->setSheetTitle(date('Ymd'));

        $width = [
            'A' => 15,
            'B' => 20,
            'C' => 15,
            'D' => 20,
            'E' => 20,
            'F' => 20,
            'G' => 20,
            'H' => 20,
            'I' => 20,
            'J' => 20,
            'K' => 20,
            'L' => 20,
            'M' => 20,
            'N' => 20,
        ];

        $downExcel->setWidth($width);

        $downExcel->setDefaultStyleAlignment();

        $downExcel->create($exportData, $header);
    }

}